--- title: The peak pattern puzzle keywords: fastai sidebar: home_sidebar summary: "Matching peak patterns " description: "Matching peak patterns " nb_path: "notebooks/40_peak-pattern-puzzle.ipynb" ---
{% raw %}
{% endraw %}

In the previous steps we have computed the hotmax spectra and within each spectrum detected peaks above the Poison noise level. All this preliminary work was needed to arrive at the central problem of MA-XRF analysis: solving the peak pattern puzzle. For each individual hotmax spectrum I would like to explain the presence of all peaks above the Poison noise level.

Before trying to assign peaks to the presence of specific elements in the scanned object, one should identify instrumental peaks that result from the physics of the instrument sensor or Rhodium anode.

{% raw %}
from maxrf4u import HotmaxAtlas 

hma = HotmaxAtlas('RP-T-1898-A-3689.datastack')

hma.plot_spectra()
2022-05-13T10:43:49.492501 image/svg+xml Matplotlib v3.4.3, https://matplotlib.org/
{% endraw %}

Or we can plot a single spectrum with HotmaxAtlas.plot_spectrum(<nr>)) to inspect a specific hotmax spectrum.

{% raw %}
hma.plot_spectrum(4, headspace=3);
{% endraw %}

Now we can start to 'explain away' all peaks...

To be continued...

{% raw %}
hma = HotmaxAtlas('RP-T-1898-A-3689.datastack')
{% endraw %} {% raw %}
fig, ax = plt.subplots(figsize=[9, 9])

n = 4 
ann_list = hma.plot_spectrum(n, ax=ax, headspace=2)

eoi_ptrns = get_patterns(eoi)

twax = ax.twinx()
plot_patterns(eoi_ptrns, ax=twax)
{% endraw %}

Module maxrf4u.peakpuzzle.py

{% raw %}

get_patterns[source]

get_patterns(elements, tube_keV=22)

Returns sorted pattern dict list, according to alpha peak energy.
{% endraw %} {% raw %}

colorize[source]

colorize(elem=None, eoi=None)

Pick fixed color from nice color map for elements of interest.
{% endraw %} {% raw %}

plot_patterns[source]

plot_patterns(ptrn_list, ax=None)

{% endraw %} {% raw %}
{% endraw %} {% raw %}
len(eoi)
31
{% endraw %} {% raw %}
get_patterns(['Fe'])
[{'elem': 'Fe',
  'name': 'Iron',
  'peaks_xy': array([[6.3941971 , 1.        ],
         [7.05452726, 0.13507831],
         [0.70435218, 0.02822656]]),
  'color': array([0.9, 0.1, 0.1])}]
{% endraw %} {% raw %}
ptrn_list = get_patterns(eoi)
{% endraw %}

Let's plot these patterns

{% raw %}
ptrn_list = get_patterns(eoi)
plot_patterns(ptrn_list)
{% endraw %} {% raw %}
ptrn_list
[{'elem': 'N',
  'peaks_xy': array([[0.3961981, 1.       ]]),
  'color': [0.6196078431372549, 0.8549019607843137, 0.8980392156862745]},
 {'elem': 'O',
  'peaks_xy': array([[0.52826413, 1.        ]]),
  'color': [0.09019607843137255, 0.7450980392156863, 0.8117647058823529]},
 {'elem': 'F',
  'peaks_xy': array([[0.67133567, 1.        ]]),
  'color': [0.8588235294117647, 0.8588235294117647, 0.5529411764705883]},
 {'elem': 'Na',
  'peaks_xy': array([[1.04552276, 1.        ]]),
  'color': [0.7372549019607844, 0.7411764705882353, 0.13333333333333333]},
 {'elem': 'Mg',
  'peaks_xy': array([[1.25462731, 1.        ]]),
  'color': [0.7803921568627451, 0.7803921568627451, 0.7803921568627451]},
 {'elem': 'Al',
  'peaks_xy': array([[1.48574287, 1.        ]]),
  'color': [0.4980392156862745, 0.4980392156862745, 0.4980392156862745]},
 {'elem': 'Si',
  'peaks_xy': array([[1.73886943, 1.        ]]),
  'color': [0.9686274509803922, 0.7137254901960784, 0.8235294117647058]},
 {'elem': 'P',
  'peaks_xy': array([[2.014007, 1.      ]]),
  'color': [0.8901960784313725, 0.4666666666666667, 0.7607843137254902]},
 {'elem': 'S',
  'peaks_xy': array([[2.31115558, 1.        ]]),
  'color': [1.0, 0.9, 0.1]},
 {'elem': 'Cl',
  'peaks_xy': array([[2.61930965, 1.        ]]),
  'color': [0.5490196078431373, 0.33725490196078434, 0.29411764705882354]},
 {'elem': 'Ag',
  'peaks_xy': array([[2.98249125, 1.        ],
         [2.64132066, 0.03711157]]),
  'color': [0.8617627896065553, 0.8617627896065553, 0.8617627896065553]},
 {'elem': 'Cd',
  'peaks_xy': array([[3.13656828, 1.        ],
         [3.33466733, 0.54499009],
         [3.95097549, 0.04265699],
         [2.77338669, 0.03710945]]),
  'color': [0.6582003733660282, 0.6582003733660282, 0.6582003733660282]},
 {'elem': 'K',
  'peaks_xy': array([[3.31265633, 1.        ],
         [3.5877939 , 0.11613478]]),
  'color': [0.7725490196078432, 0.6901960784313725, 0.8352941176470589]},
 {'elem': 'Sn',
  'peaks_xy': array([[3.44472236, 1.        ],
         [3.68684342, 0.86217419],
         [4.3801901 , 0.08792298],
         [4.12706353, 0.06867461],
         [3.04852426, 0.03736927]]),
  'color': [0.9810565997395585, 0.8168056337199403, 0.8900357854757446]},
 {'elem': 'Ca',
  'peaks_xy': array([[3.68684342, 1.        ],
         [4.0170085 , 0.12565047]]),
  'color': [0.5803921568627451, 0.403921568627451, 0.7411764705882353]},
 {'elem': 'I',
  'peaks_xy': array([[3.93996998, 1.        ],
         [4.24812406, 0.834673  ],
         [5.07353677, 0.08740968],
         [4.7983992 , 0.08131471],
         [3.48874437, 0.03792133]]),
  'color': [0.9325913996040441, 0.6330005226112336, 0.8487053301493133]},
 {'elem': 'Ba',
  'peaks_xy': array([[4.46823412, 1.        ],
         [4.84242121, 0.8065798 ],
         [5.16158079, 0.16520084],
         [5.53576788, 0.09280552],
         [5.81090545, 0.0831585 ],
         [3.95097549, 0.03860967]]),
  'color': [0.8539442814235829, 0.7446473541924543, 0.721494327539966]},
 {'elem': 'Ti',
  'peaks_xy': array([[4.51225613, 1.        ],
         [4.93046523, 0.13026382],
         [0.44022011, 0.01364528]]),
  'color': [1.0, 0.596078431372549, 0.5882352941176471]},
 {'elem': 'V',
  'peaks_xy': array([[4.95247624, 1.        ],
         [5.42571286, 0.13198924],
         [0.50625313, 0.01739971]]),
  'color': [0.8392156862745098, 0.15294117647058825, 0.1568627450980392]},
 {'elem': 'Cr',
  'peaks_xy': array([[5.41470735, 1.        ],
         [5.94297149, 0.12885503],
         [0.57228614, 0.02085085]]),
  'color': [0.596078431372549, 0.8745098039215686, 0.5411764705882353]},
 {'elem': 'Mn',
  'peaks_xy': array([[5.89894947, 1.        ],
         [6.49324662, 0.13436239],
         [0.63831916, 0.02319039]]),
  'color': [0.17254901960784313, 0.6274509803921569, 0.17254901960784313]},
 {'elem': 'Fe',
  'peaks_xy': array([[6.3941971 , 1.        ],
         [7.05452726, 0.13507831],
         [0.70435218, 0.02822656]]),
  'color': [0.9, 0.1, 0.1]},
 {'elem': 'Co',
  'peaks_xy': array([[6.92246123, 1.        ],
         [7.64882441, 0.13586803],
         [0.7813907 , 0.03067365]]),
  'color': [1.0, 0.4980392156862745, 0.054901960784313725]},
 {'elem': 'Ni',
  'peaks_xy': array([[7.47273637, 1.        ],
         [8.26513257, 0.13651501],
         [0.85842921, 0.03262745]]),
  'color': [0.6823529411764706, 0.7803921568627451, 0.9098039215686274]},
 {'elem': 'Cu',
  'peaks_xy': array([[8.04502251, 1.        ],
         [8.90345173, 0.13519763],
         [0.93546773, 0.03435044]]),
  'color': [0.1, 0.9, 0.3]},
 {'elem': 'Zn',
  'peaks_xy': array([[8.62831416, 1.        ],
         [9.57478739, 0.13855054],
         [1.02351176, 0.03552537]]),
  'color': [0.7503608106413998, 0.9102271552918426, 0.9375127465007698]},
 {'elem': 'Hg',
  'peaks_xy': array([[ 9.981991  ,  1.        ],
         [11.84192096,  0.72592091],
         [ 2.22311156,  0.22576894],
         [13.83391696,  0.12703671],
         [ 8.72736368,  0.0539311 ],
         [14.20810405,  0.03217489],
         [ 1.71685843,  0.0255982 ],
         [10.64232116,  0.01723941]]),
  'color': [0.697834944396196, 0.5209247146284669, 0.47985790076901175]},
 {'elem': 'As',
  'peaks_xy': array([[10.53226613,  1.        ],
         [11.72086043,  0.15092996],
         [ 1.28764382,  0.04239893]]),
  'color': [0.23610902801167039, 0.8381621642481365, 0.882384963950054]},
 {'elem': 'Pb',
  'peaks_xy': array([[10.54327164,  1.        ],
         [12.61230615,  0.86061392],
         [ 2.37718859,  0.22474819],
         [14.76938469,  0.13372169],
         [ 9.1895948 ,  0.0562375 ],
         [12.30415208,  0.04622662],
         [15.17658829,  0.03288477],
         [ 1.82691346,  0.02578214],
         [11.34667334,  0.01782932]]),
  'color': [0.2, 0.2, 0.2]},
 {'elem': 'Br',
  'peaks_xy': array([[11.90795398,  1.        ],
         [13.29464732,  0.15988785],
         [ 1.49674837,  0.04610553]]),
  'color': [0.9127300741924363, 0.9127300741924363, 0.7008214073084114]},
 {'elem': 'Sr',
  'peaks_xy': array([[14.14207104,  1.        ],
         [15.83691846,  0.17388333],
         [ 1.82691346,  0.05557395]]),
  'color': [0.8328573088421117, 0.8355125433615939, 0.298512995129362]}]
{% endraw %} {% raw %}
def get_instrument_patterns(datastack_file, anode='Rh', prominence=0.35): 
    '''Create instrument peak pattern dictionaries for sensor peak and Compton and elastic anode peaks.'''
    
    ds = maxrf4u.DataStack(datastack_file)
    
    # read max spectrum 
    ds = maxrf4u.DataStack(datastack_file)
    x_keVs = ds.read(ds.MAXRF_ENERGIES)
    y_max = ds.read(ds.MAXRF_MAXSPECTRUM)

    # locate peaks in max spectrum 
    peak_indices, _ = ssg.find_peaks(y_max, prominence=prominence)
    peaks_x = x_keVs[peak_indices]
    
    # assumes first peak is (negative) sensor peak 
    sensor_keV = peaks[0] 
    
    sensor_ptrn = {'source': 'SENSOR', 
                   'peaks_xy': np.array([[sensor_keV, 1]])}
    
    # anode peak pattern (including Compton)
    rhodium_peaks_x = mos.XFluo('Rh', tube_keV=40).peak_energies 
    Rh
    
    
    #anode_ptrn = 
     
    return peaks_x
    
    
{% endraw %} {% raw %}
datastack_file = 'RP-T-1898-A-3689.datastack'
{% endraw %} {% raw %}
ds = maxrf4u.DataStack(datastack_file)

y_sum = ds.read('maxrf_sumspectrum')
y_sum_without_sensor_peak = y_sum.copy()
y_sum_without_sensor_peak[x_keV < 1] = 0
Rh_Compton_i = np.argmax(y_sum_without_sensor_peak)
Rh_Compton_keV = x_keV[Rh_Compton_i]
Rh_Compton_keV
{% endraw %} {% raw %}
rhodium_spectrum = mos.XFluo('Rh', tube_keV=40)
{% endraw %} {% raw %}
rhodium_spectrum.peak_intensities
array([0.08118119, 1.        , 0.244193  , 0.04090913])
{% endraw %} {% raw %}
rhodium_spectrum.peak_energies
array([ 2.70135068, 20.21010505, 22.71135568, 23.17158579])
{% endraw %} {% raw %}
maxrf4u.RHODIUM_Ka
20.210105052526263
{% endraw %} {% raw %}
peaks_x = get_instrument_patterns('RP-T-1898-A-3689.datastack')
peaks_x
array([-0.02864804,  0.53326082,  2.37953279,  2.62035087,  3.30266878,
        3.68396408,  4.00505485,  4.50675919,  4.84791815,  5.89146317,
        6.4032016 ,  7.06545133,  8.04879184,  8.65083705,  8.89165513,
        9.22277999, 10.55731354, 11.67109718, 12.6444036 , 14.46057331,
       14.80173226, 18.84546925, 20.21010505, 21.012832  ])
{% endraw %}

Let's plot these patterns...

{% raw %}
eoi
array(['N', 'O', 'F', 'Na', 'Mg', 'Al', 'Si', 'P', 'S', 'Cl', 'K', 'Ca',
       'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', 'As', 'Br',
       'Sr', 'Ag', 'Cd', 'Sn', 'I', 'Ba', 'Hg', 'Pb'], dtype='<U3')
{% endraw %}

First we need to add the ANODE and SENSOR patterns.

{% raw %}
ptrn_list
[{'elem': 'N', 'peaks_xy': array([[0.3961981, 1.       ]])},
 {'elem': 'O', 'peaks_xy': array([[0.52826413, 1.        ]])},
 {'elem': 'F', 'peaks_xy': array([[0.67133567, 1.        ]])},
 {'elem': 'Na', 'peaks_xy': array([[1.04552276, 1.        ]])},
 {'elem': 'Mg', 'peaks_xy': array([[1.25462731, 1.        ]])},
 {'elem': 'Al', 'peaks_xy': array([[1.48574287, 1.        ]])},
 {'elem': 'Si', 'peaks_xy': array([[1.73886943, 1.        ]])},
 {'elem': 'P', 'peaks_xy': array([[2.014007, 1.      ]])},
 {'elem': 'S', 'peaks_xy': array([[2.31115558, 1.        ]])},
 {'elem': 'Cl', 'peaks_xy': array([[2.61930965, 1.        ]])},
 {'elem': 'Ag',
  'peaks_xy': array([[2.98249125, 1.        ],
         [2.64132066, 0.03711157]])},
 {'elem': 'Cd',
  'peaks_xy': array([[3.13656828, 1.        ],
         [3.33466733, 0.54499009],
         [3.95097549, 0.04265699],
         [2.77338669, 0.03710945]])},
 {'elem': 'K',
  'peaks_xy': array([[3.31265633, 1.        ],
         [3.5877939 , 0.11613478]])},
 {'elem': 'Sn',
  'peaks_xy': array([[3.44472236, 1.        ],
         [3.68684342, 0.86217419],
         [4.3801901 , 0.08792298],
         [4.12706353, 0.06867461],
         [3.04852426, 0.03736927]])},
 {'elem': 'Ca',
  'peaks_xy': array([[3.68684342, 1.        ],
         [4.0170085 , 0.12565047]])},
 {'elem': 'I',
  'peaks_xy': array([[3.93996998, 1.        ],
         [4.24812406, 0.834673  ],
         [5.07353677, 0.08740968],
         [4.7983992 , 0.08131471],
         [3.48874437, 0.03792133]])},
 {'elem': 'Ba',
  'peaks_xy': array([[4.46823412, 1.        ],
         [4.84242121, 0.8065798 ],
         [5.16158079, 0.16520084],
         [5.53576788, 0.09280552],
         [5.81090545, 0.0831585 ],
         [3.95097549, 0.03860967]])},
 {'elem': 'Ti',
  'peaks_xy': array([[4.51225613, 1.        ],
         [4.93046523, 0.13026382],
         [0.44022011, 0.01364528]])},
 {'elem': 'V',
  'peaks_xy': array([[4.95247624, 1.        ],
         [5.42571286, 0.13198924],
         [0.50625313, 0.01739971]])},
 {'elem': 'Cr',
  'peaks_xy': array([[5.41470735, 1.        ],
         [5.94297149, 0.12885503],
         [0.57228614, 0.02085085]])},
 {'elem': 'Mn',
  'peaks_xy': array([[5.89894947, 1.        ],
         [6.49324662, 0.13436239],
         [0.63831916, 0.02319039]])},
 {'elem': 'Fe',
  'peaks_xy': array([[6.3941971 , 1.        ],
         [7.05452726, 0.13507831],
         [0.70435218, 0.02822656]])},
 {'elem': 'Co',
  'peaks_xy': array([[6.92246123, 1.        ],
         [7.64882441, 0.13586803],
         [0.7813907 , 0.03067365]])},
 {'elem': 'Ni',
  'peaks_xy': array([[7.47273637, 1.        ],
         [8.26513257, 0.13651501],
         [0.85842921, 0.03262745]])},
 {'elem': 'Cu',
  'peaks_xy': array([[8.04502251, 1.        ],
         [8.90345173, 0.13519763],
         [0.93546773, 0.03435044]])},
 {'elem': 'Zn',
  'peaks_xy': array([[8.62831416, 1.        ],
         [9.57478739, 0.13855054],
         [1.02351176, 0.03552537]])},
 {'elem': 'Hg',
  'peaks_xy': array([[ 9.981991  ,  1.        ],
         [11.84192096,  0.72592091],
         [ 2.22311156,  0.22576894],
         [13.83391696,  0.12703671],
         [ 8.72736368,  0.0539311 ],
         [14.20810405,  0.03217489],
         [ 1.71685843,  0.0255982 ],
         [10.64232116,  0.01723941]])},
 {'elem': 'As',
  'peaks_xy': array([[10.53226613,  1.        ],
         [11.72086043,  0.15092996],
         [ 1.28764382,  0.04239893]])},
 {'elem': 'Pb',
  'peaks_xy': array([[10.54327164,  1.        ],
         [12.61230615,  0.86061392],
         [ 2.37718859,  0.22474819],
         [14.76938469,  0.13372169],
         [ 9.1895948 ,  0.0562375 ],
         [12.30415208,  0.04622662],
         [15.17658829,  0.03288477],
         [ 1.82691346,  0.02578214],
         [11.34667334,  0.01782932]])},
 {'elem': 'Br',
  'peaks_xy': array([[11.90795398,  1.        ],
         [13.29464732,  0.15988785],
         [ 1.49674837,  0.04610553]])},
 {'elem': 'Sr',
  'peaks_xy': array([[14.14207104,  1.        ],
         [15.83691846,  0.17388333],
         [ 1.82691346,  0.05557395]])}]
{% endraw %}

Then, we need to start matching the peak patterns.